#!/usr/bin/python
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import random
import time
from concurrent import futures

import grpc

import demo_pb2
import demo_pb2_grpc
from grpc_health.v1 import health_pb2
from grpc_health.v1 import health_pb2_grpc

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (BatchSpanProcessor)
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from elasticsearch import Elasticsearch
from loguru import logger
from datetime import datetime
tracer_provider = TracerProvider()
trace.set_tracer_provider(tracer_provider)
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))


def send_es_log(es_client: Elasticsearch, msg: str):
    es_client.index(
        index='service-log',
        document={
            'msg': msg,
            '@timestamp': datetime.now().isoformat() + "+0800"
        }
    )
    logger.info(f'Write into es: {msg}')


class LogService(demo_pb2_grpc.LogServiceServicer):
    def __init__(self, es_client: Elasticsearch):
        self.es_client = es_client

    def SendLogMessage(self, request, context):
        msg = request.msg
        logger.info(f'Received: {msg}')
        send_es_log(self.es_client, msg)

        # Sleep some time for emulation
        time.sleep(0.01)

        response = demo_pb2.SendLogMessageRequest()
        return response

    def Check(self, request, context):
        return health_pb2.HealthCheckResponse(
            status=health_pb2.HealthCheckResponse.SERVING)

    def Watch(self, request, context):
        return health_pb2.HealthCheckResponse(
            status=health_pb2.HealthCheckResponse.UNIMPLEMENTED)


if __name__ == "__main__":
    logger.info("initializing logservice")

    port = os.environ.get('PORT', "8080")
    es_addr = os.environ.get('ES_ADDR', 'http://eck-es-http:9200')
    es_user = os.environ.get('ES_USER', 'admin')
    es_password = os.environ.get('ES_PASSWORD', '123456')

    # Connecto to es
    logger.info(f'Connecting to es server: {es_addr}')
    try:
        es_client = Elasticsearch(
            es_addr,
            basic_auth=(es_user, es_password)
        )
        logger.info('Connected to es server.')
    except Exception as err:
        logger.error(str(err))
        exit(-1)

    # create gRPC server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10),)

    # add class to gRPC server
    service = LogService(es_client)
    demo_pb2_grpc.add_LogServiceServicer_to_server(service, server)
    health_pb2_grpc.add_HealthServicer_to_server(service, server)

    # start server
    logger.info("listening on port: " + port)
    server.add_insecure_port('[::]:'+port)
    server.start()

    # keep alive
    try:
         while True:
            time.sleep(10000)
    except KeyboardInterrupt:
            server.stop(0)
